/**
 * 
 */
package fbv.commun.dataTools.negocio;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import fbv.commun.dataTools.servico.Controlador;
import fbv.commun.dataTools.servico.EntidadePadrao;
import fbv.commun.dataTools.servico.ObjetoVO;
import fbv.commun.excecoes.FBVArgumentoIlegalException;
import fbv.commun.excecoes.FBVException;
import fbv.commun.util.CommunConstantes;
import fbv.commun.util.DTRMensagens;
import fbv.commun.util.Util;

/**
 * @author Max Santu
 * 
 */
public abstract class ControladorImpl implements Controlador {
	/**
	 * 
	 */
	public ControladorImpl() {
		// TODO Auto-generated constructor stub
	}
	
	protected abstract EntidadeDAO getEntidadeDAO();
	
	private Integer inserir(EntidadePadrao entidade) throws FBVException {
		Integer novoId;
		((EntidadePardraoImpl) entidade).validarDados();
		try {
			getEntidadeDAO().comecarTranzacao();
			tratarPreInsercao(entidade);
			novoId = getEntidadeDAO().inserir(entidade);
			tratarPosInsercao(entidade);
			getEntidadeDAO().finalizarTranzacao();
		} finally {
			getEntidadeDAO().fecharConexao();
		}

		return novoId;
	}
	
	public Integer inserir(Map<String, String> campos) throws NumberFormatException, FBVException {
		return inserir(montarEntidadePadao(campos));
	}
	
	/**
	 * @param Map campos
	 * @return EntidadePadrao
	 */
	protected abstract EntidadePadrao montarEntidadePadao(Map<String, String> campos) throws FBVException;
	
	public void alterar(Map<String, String> campos) throws NumberFormatException, FBVException {
		alterar(montarEntidadePadao(campos));
	}
	
	private void alterar(EntidadePadrao entidade) throws FBVException {
		((EntidadePardraoImpl) entidade).validarDados();
		try {
			getEntidadeDAO().comecarTranzacao();
			tratarPreAtualizacao(entidade);
			getEntidadeDAO().alterar(entidade);
			tratarPosAtualizacao(entidade);
			getEntidadeDAO().finalizarTranzacao();
		} finally {
			getEntidadeDAO().fecharConexao();
		}
	}
	
	public void excluir(Integer id) throws NumberFormatException, FBVException {
		excluir(consultar(id));
	}
	
	private void excluir(EntidadePadrao entidade) throws FBVException {
		try {
			getEntidadeDAO().comecarTranzacao();
			tratarPreExclusao(entidade);
			getEntidadeDAO().excluir(entidade);
			tratarPosExclusao(entidade);
			getEntidadeDAO().finalizarTranzacao();
		} finally {
			getEntidadeDAO().fecharConexao();
		}
	}
	
	/**
	 * TODO Retirar o Public e fazer selecionar no DAO recebendo uma conexao
	 * @param id
	 * @return
	 * @throws FBVException
	 */
	public EntidadePadrao consultar(Integer id) throws FBVException {
		EntidadePadrao entidadePadrao; 
		try {
			getEntidadeDAO().comecarTranzacao();
			entidadePadrao = getEntidadeDAO().selecionar(id, true);
			getEntidadeDAO().finalizarTranzacao();
		} finally {
			getEntidadeDAO().fecharConexao();
		}
		
		return entidadePadrao;
	}
	
	protected Collection consultarTodos() throws FBVException {
		Collection collection;		
		try{
			getEntidadeDAO().comecarTranzacao();
			collection = getEntidadeDAO().selecionarTodas(false);
			getEntidadeDAO().finalizarTranzacao();			
		}
		finally{
			getEntidadeDAO().fecharConexao();
		}
		return collection;
	}
	
	public ObjetoVO selecionar(String id) throws FBVException {
		if (Util.isCampoVazio(id)){
			String[] complMsg = {"Argumento NULL invalido"};
			throw new FBVArgumentoIlegalException(CommunConstantes.COMMUN_BUNDLE, DTRMensagens.MSG000, complMsg);
		}
		return montarObjetoVO(consultar(Integer.valueOf(id)));
	}
	
	public Collection<ObjetoVO> selecionarTodos() throws FBVException {
		Collection<ObjetoVO> retorno = new ArrayList<ObjetoVO> ();
		Collection<EntidadePadrao> entidadeColecao = consultarTodos();
		
		for (Iterator iterator = entidadeColecao.iterator(); iterator.hasNext();) {
			EntidadePadrao entidadePadrao = (EntidadePadrao) iterator.next();
			retorno.add(montarObjetoVO(entidadePadrao));
		}
		
		return retorno;
	}
	
	protected abstract ObjetoVO montarObjetoVO(EntidadePadrao entidade);

	protected void tratarPreInsercao(EntidadePadrao entidade) {

	}

	protected void tratarPosInsercao(EntidadePadrao entidade) {

	}

	protected void tratarPreAtualizacao(EntidadePadrao entidade) {

	}

	protected void tratarPosAtualizacao(EntidadePadrao entidade) {

	}

	protected void tratarPreExclusao(EntidadePadrao entidade) {

	}

	protected void tratarPosExclusao(EntidadePadrao entidade) {

	}
}
